<script lang="ts" setup>
import { useIntersectionObserver } from '@vueuse/core';
import { onMounted, ref, shallowRef, watch } from 'vue';

const props = defineProps<{
  component: () => Promise<any>;
  forceLoad?: boolean;
}>();

const el = ref<HTMLElement | null>(null);
const innerComp = shallowRef();

function loadComponent() {
  if (!innerComp.value) {
    props.component().then(mod => {
      innerComp.value = mod.default || mod;
    });
  }
}

onMounted(() => {
  const { stop } = useIntersectionObserver(
    el,
    ([{ isIntersecting }]) => {
      if (isIntersecting) {
        loadComponent();
        stop();
      }
    },
    { threshold: 0.1 },
  );
});

watch(
  () => props.forceLoad,
  val => {
    if (val) {
      loadComponent();
    }
  },
  { immediate: true },
);
</script>

<template>
  <div ref="el" class="min-h-40vh">
    <component :is="innerComp" v-if="innerComp" />
  </div>
</template>
